home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Applications / Nuntius 1.2 / src / Nuntius / FileTools.cp < prev    next >
Encoding:
Text File  |  1994-03-16  |  8.1 KB  |  340 lines  |  [TEXT/MPS ]

  1. // Copyright © 1992 Peter Speck, speck@dat.ruc.dk. All rights reserved.
  2. // FileTools.cp
  3.  
  4. #include "FileTools.h"
  5. #include "Tools.h"
  6. #include "UThread.h"
  7.  
  8. #include <RsrcGlobals.h>
  9.  
  10. #include <Errors.h>
  11. #include <Packages.h>
  12.  
  13. #pragma segment MyTools
  14.  
  15. #define qDebugAsyncFile qDebug & 0
  16.  
  17. Boolean FileExist(const FSSpec &spec)
  18. {
  19.     FInfo fndrInfo;
  20.     short errNo = HGetFInfo(spec.vRefNum, spec.parID, spec.name, fndrInfo);
  21.     if (errNo == fnfErr) 
  22.         return false;
  23.     FailOSErr(errNo);
  24.     return true;
  25. }
  26.  
  27. Boolean FileExist(TFile *file)
  28. {
  29.     if (file->fDataRefNum != kNoFileRefnum || file->fRsrcRefNum != kNoFileRefnum)
  30.         return true; // file open: file must exist
  31.     FSSpec spec;
  32.     file->GetFileSpec(spec);
  33.     return FileExist(spec);
  34. }
  35.  
  36. void ResolveAliasFile(TFile *file)
  37. {
  38.     Boolean targetIsFolder, wasAliased;
  39.     FSSpec spec;
  40.     file->GetFileSpec(spec);
  41.     OSErr err = ResolveAliasFile(spec, true, targetIsFolder, wasAliased);
  42.     if (wasAliased)
  43.         file->Specify(spec);
  44.     if (err != fnfErr)
  45.         FailOSErr(err);
  46. }
  47.  
  48. void MyRenameFile(TFile *file, const CStr255 &newname)
  49. {
  50.     file->RenameFile(newname);
  51.     CopyCString2String(newname, file->fFileSpec.name); // RenameFile() doesn't update this
  52. }
  53.  
  54. void CheckFilenameSanity(CStr255 &filename)
  55. {
  56. // substitute invalid chars
  57.     unsigned char ch;
  58.     if (gConfiguration.hasAUX)
  59.     {
  60.         for (short i = filename.Length(); i; i--)
  61.         {
  62.             ch = (unsigned char)filename[i];
  63.             if (ch == '/' || ch == '.')
  64.                 filename[i] = '_';
  65.             else if (ch < 32)
  66.                 filename.Delete(i, 1);
  67.         }
  68.     }
  69.     else // HFS (I presume!)
  70.     {
  71.         for (short i = filename.Length(); i; i--)
  72.         {
  73.             ch = (unsigned char)filename[i];
  74.             if (ch == ':' || ch < 32)
  75.                 filename[i] = '-';
  76.         }
  77.         if (filename.Length() && filename[1] == '.')
  78.             filename[1] = '•';
  79.     }
  80.     if (filename.Length() > 31) // dunno with A/UX
  81.         filename.Length() = 31;
  82.     if (filename.Length() == 0)
  83.         MyGetIndString(filename, kUntitledFileName);
  84. }
  85.  
  86. void MakeFilenameUnique(FSSpec &spec)
  87. {
  88.     if (!FileExist(spec))
  89.         return;
  90.     CStr255 s(spec.name);
  91.     short pos = s.Pos("•");
  92.     if (pos)
  93.         s.Delete(pos, s.Length() - pos + 1);
  94.     long nr = 0;
  95.     while (FileExist(spec))
  96.     {
  97.         nr++;
  98.         CStr255 num;
  99.         NumToString(nr, num);
  100.         num.Insert("•", 1);
  101.         if (s.Length() + num.Length() > 31)
  102.             s.Length() = 31 - num.Length();
  103.         CopyCString2String(s + num, spec.name);
  104.     }
  105. }
  106.  
  107. void MakeFilenameUnique(TFile *file)
  108. {
  109.     FSSpec spec;
  110.     file->GetFileSpec(spec);
  111.     MakeFilenameUnique(spec);
  112.     if (file->fDataRefNum != kNoFileRefnum || file->fRsrcRefNum != kNoFileRefnum)
  113.         MyRenameFile(file, spec.name);
  114.     else
  115.         file->Specify(spec);
  116. }
  117.  
  118. void FlushVols()
  119. {
  120.     CStr255 name("");
  121.     short vRefNum;
  122.     short index = 0;
  123.     while (true)
  124.     {
  125.         short errNo = GetIndVolume(++index, vRefNum);
  126.         if (errNo == nsvErr)
  127.             break; // ignore all others!
  128.         FlushVol(&name, vRefNum);
  129.     }
  130. }
  131.  
  132. void GoInsideFolder(FSSpec &spec)
  133. {
  134.     CStr255 s;
  135.     s = spec.name;
  136.     CheckFilenameSanity(s);
  137.     CopyCString2String(s, spec.name);
  138.     short errNo;
  139.     Boolean targetIsFolder, wasAliased;
  140.     errNo = ResolveAliasFile(spec, true, targetIsFolder, wasAliased);
  141.     if (errNo != fnfErr)
  142.         FailOSErr(errNo);
  143.     CInfoPBRec info;
  144.     info.dirInfo.ioCompletion = nil;
  145.     info.dirInfo.ioNamePtr = StringPtr(spec.name);
  146.     info.dirInfo.ioVRefNum = spec.vRefNum;
  147.     info.dirInfo.ioFDirIndex = 0;
  148.     info.dirInfo.ioDrDirID = spec.parID;
  149.     errNo = PBGetCatInfoSync(&info);
  150.     if (errNo == fnfErr)
  151.     {
  152.         long createdDirID;
  153.         FailOSErr(FSpDirCreate(spec, smRoman, createdDirID));
  154.         spec.parID = createdDirID;
  155.     }
  156.     else
  157.     {
  158.         FailOSErr(errNo);
  159.         spec.parID = info.dirInfo.ioDrDirID;
  160.     }
  161. }
  162.  
  163. void GoGroupFile(const CStr255 &groupName, FSSpec &spec)
  164. {
  165. #if qDebug
  166.     long numIter = 0;
  167. #endif
  168.     CStr255 gn(groupName);
  169.     short dotPos;
  170.     while (gn.Length())
  171.     {
  172.         const short maxGroupNameLength = 29;
  173.         if (gn.Length() <= maxGroupNameLength)
  174.         {
  175.             CopyCString2String(gn, spec.name);
  176.             return;
  177.         }
  178.         dotPos = maxGroupNameLength;
  179.         while (dotPos && gn[dotPos] != '.')
  180.             dotPos--;
  181.         CStr255 s, suffix;
  182.         MyGetIndString(suffix, kLongGroupNameFolderSuffix);
  183.         if (dotPos <= 1)
  184.         {
  185.             s = gn.Copy(1, maxGroupNameLength) + suffix;
  186.             gn.Delete(1, maxGroupNameLength);
  187.         }
  188.         else
  189.         {
  190.             s = gn.Copy(1, dotPos - 1) + suffix;
  191.             gn.Delete(1, dotPos);
  192.         }
  193. #if qDebug
  194.         if (++numIter > 10)
  195.             ProgramBreak("Endless loop en GoGroupFile");
  196. #endif
  197.         CopyCString2String(s, spec.name);
  198.         GoInsideFolder(spec);
  199.     }
  200. }
  201.  
  202. void GetPathNameFromDirID(short vRefNum, long dirID, CStr255 &pathName)
  203. {
  204. #if qDebug & 0
  205.     fprintf(stderr, "GetPathNameFromDirID: \n");
  206.     fprintf(stderr, "  vRefNum = %hd\n", vRefNum);
  207.     fprintf(stderr, "  dirID = %ld\n", dirID);
  208. #endif
  209.     CInfoPBRec block;
  210.     CStr255 directoryName = "";
  211.     pathName = "";
  212.     block.dirInfo.ioNamePtr = StringPtr(&directoryName);
  213.     block.dirInfo.ioDrParID = dirID;
  214.     do
  215.     {
  216.         block.dirInfo.ioVRefNum = vRefNum;
  217.         block.dirInfo.ioFDirIndex = -1;
  218.         block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
  219.         short err = PBGetCatInfoSync(&block);
  220.         if (block.dirInfo.ioDrDirID == block.dirInfo.ioDrParID)
  221.         {
  222. #if qDebug
  223.             if (block.dirInfo.ioDrDirID != 2)
  224.                 fprintf(stderr, "GetPathName: ioDrDirID == ioDrParID == %ld\n", long(block.dirInfo.ioDrDirID));
  225. #endif
  226.             break; // at root at a shared folder!
  227.         }
  228.         if (gConfiguration.hasAUX)
  229.         {
  230.             if (directoryName[1] != '/')
  231.                 // If this isn't root (i.e. "/"), append a slash ('/')
  232.                 directoryName += '/';
  233.         }
  234.         else
  235.         {
  236.             directoryName += ':';
  237.         }
  238.         pathName.Insert(directoryName, 1);
  239.     }
  240.     while (block.dirInfo.ioDrDirID != fsRtDirID);
  241. }
  242.  
  243.  
  244. void ChangeFileTypeAndCreator(TFile *file, OSType newCreator, OSType newType)
  245. {
  246.     FInfo fndrInfo;
  247.     FailOSErr(file->GetFinderInfo(fndrInfo));
  248.     fndrInfo.fdType = newType;
  249.     fndrInfo.fdCreator = newCreator;
  250.     FSSpec theFileSpec = file->fFileSpec;                    
  251.     FailOSErr(FSpSetFInfo(theFileSpec, fndrInfo));
  252. // modify folder so Finder™ updates the display
  253.     CInfoPBRec info;
  254.     info.dirInfo.ioFDirIndex = -1;
  255.     info.dirInfo.ioDrDirID = file->fFileSpec.parID;
  256.     info.dirInfo.ioVRefNum = file->fFileSpec.vRefNum;
  257.     info.dirInfo.ioNamePtr = nil;
  258.     FailOSErr(PBGetCatInfoSync(&info));
  259.     GetDateTime(info.dirInfo.ioDrMdDat);
  260.     short errNo = PBSetCatInfoSync(&info);
  261. #if qDebug
  262.     if (errNo)
  263.     {
  264.         fprintf(stderr, "Could not set modification date on folder, err = %hd\n", errNo);
  265.         ProgramBreak(gEmptyString);
  266.     }
  267. #endif
  268. }
  269.  
  270. void AskFileName(const CStr255 &prompt, const CStr255 &defaultFilename, FSSpec &spec)
  271. {
  272.     // should make one which Yield time to other threads
  273.     FailOSErr(MAInteractWithUser(kNoTimeOut, gNotificationPtr, gMacAppAppleEventIdleProc));
  274.     StandardFileReply customReply;
  275.     CopyCString2String(defaultFilename, customReply.sfFile.name);
  276.     CustomPutFile(prompt, defaultFilename, customReply, sfPutDialogID, CPoint(-1, -1), nil, gModalFilterYDProcPtr, nil, nil, nil);
  277.     if (!customReply.sfGood)
  278.         Failure(0, 0);
  279.     spec = customReply.sfFile;
  280. }
  281.  
  282.  
  283. void WriteASyncToFile(ParamBlockRec &pb, TFile *file, const void *p, long numBytes)
  284. {
  285.     Ptr fromP = Ptr(p);
  286.     while (numBytes > 0)
  287.     {
  288.         BlockSet(Ptr(&pb), sizeof(pb), 0);
  289.         pb.ioParam.ioRefNum = file->fDataRefNum;
  290.         pb.ioParam.ioBuffer = fromP;
  291.         pb.ioParam.ioReqCount = numBytes;
  292.         pb.ioParam.ioPosMode = fsFromMark;
  293.         pb.ioParam.ioPosOffset = 0;
  294.         FailOSErr(PBWriteAsync(&pb));
  295.         if (pb.ioParam.ioResult == 1)
  296.         {
  297. #if qDebugAsyncFile
  298.             fprintf(stderr, "Waiting for async file write (%ld bytes)\n", numBytes);
  299. #endif
  300.             while (pb.ioParam.ioResult == 1)
  301.                 gCurThread->YieldTime();
  302. #if qDebugAsyncFile
  303.             fprintf(stderr, "Async file write done\n");
  304. #endif
  305.         }
  306.         FailOSErr(pb.ioParam.ioResult);
  307.         numBytes -= pb.ioParam.ioActCount;
  308.         fromP += pb.ioParam.ioActCount;
  309.     }
  310. }
  311.  
  312. void ReadASyncFromFile(ParamBlockRec &pb, TFile *file, void *p, long &numBytes)
  313. {
  314.     if (numBytes <= 0)
  315.         return;
  316.     BlockSet(Ptr(&pb), sizeof(pb), 0);
  317.     pb.ioParam.ioRefNum = file->fDataRefNum;
  318.     pb.ioParam.ioBuffer = Ptr(p);
  319.     pb.ioParam.ioReqCount = numBytes;
  320.     pb.ioParam.ioPosMode = fsFromMark;
  321.     pb.ioParam.ioPosOffset = 0;
  322.     OSErr err = PBReadAsync(&pb);
  323.     if (err != eofErr)
  324.         FailOSErr(err);
  325.     if (pb.ioParam.ioResult == 1)
  326.     {
  327. #if qDebugAsyncFile
  328.         fprintf(stderr, "Waiting for async file read (%ld bytes)\n", numBytes);
  329. #endif
  330.         while (pb.ioParam.ioResult == 1)
  331.             gCurThread->YieldTime();
  332. #if qDebugAsyncFile
  333.         fprintf(stderr, "Async file read done (%ld)\n", pb.ioParam.ioActCount);
  334. #endif
  335.     }
  336.     if (pb.ioParam.ioResult != eofErr || pb.ioParam.ioActCount == 0)
  337.         FailOSErr(pb.ioParam.ioResult);
  338.     numBytes = pb.ioParam.ioActCount;
  339. }
  340.